/*
 * Javlov - a Java toolkit for reinforcement learning with multi-agent support.
 * 
 * Copyright (c) 2009 Matthijs Snel
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.javlov.world.phys2d;

import java.awt.Color;
import java.util.List;

import org.jdom.Element;

import net.javlov.world.Body;
import net.javlov.world.World;
import net.javlov.world.XMLWorldBuilder;
import net.phys2d.raw.shapes.StaticBox;

public class Phys2DWorldBuilder extends XMLWorldBuilder {
	
	@Override
	public void configBody(Body b, String x, String y, String width, String height) {
		if ( !(b instanceof Phys2DBody) )
			throw new IllegalArgumentException(b.getClass().toString());
		Phys2DBody p2db = (Phys2DBody) b;
		float xf = 0, yf = 0;
		if ( x != null )
			xf = Float.parseFloat(x);
		if ( y != null )
			yf = Float.parseFloat(y);
		p2db.setPosition(xf, yf);
	}
	
	@Override
	protected void configBodyGroup(Element objGroupEl, List<Body> bodies, World w, String onInit, String onReset) {
		if ( !(w instanceof Phys2DWorld) )
			throw new IllegalArgumentException(w.getClass().toString());
		Phys2DWorld p2dw = (Phys2DWorld) w;
		Color color;
		String strColor = objGroupEl.getAttributeValue("color");
		if ( strColor == null )
			color = Color.black;
		else {
			String[] strRGB = strColor.split(" ");
			color = new Color( Float.parseFloat(strRGB[0]),
								Float.parseFloat(strRGB[1]),
								Float.parseFloat(strRGB[2]));
		}
		
		for ( Body b : bodies ) {
			p2dw.addConfigRule( makeRule(b, onInit, onReset) );
			((Phys2DBody) b).getShape().setColor(color);
		}	
	}
	
	static ConfigRule makeRule(Body b, String onInit, String onReset) {
		if ( !(b instanceof Phys2DBody) )
			throw new IllegalArgumentException(b.getClass().toString());
		Phys2DBody p2db = (Phys2DBody) b;
		String s[] = onInit.split(",");
		int initPosRule = Integer.parseInt(s[0]),
			initRotRule = Integer.parseInt(s[1]);
		s = onReset.split(",");
		int resetPosRule = Integer.parseInt(s[0]),
			resetRotRule = Integer.parseInt(s[1]);
		ConfigRule rule = new ConfigRule(p2db);
		rule.setInitConfig(initPosRule, initRotRule);
		rule.setResetConfig(resetPosRule, resetRotRule);
		return rule;
	}
	
	@Override
	protected void configWorld(World w, String width, String height) {
		if ( !(w instanceof Phys2DWorld) )
			throw new IllegalArgumentException(w.getClass().toString());
		double wi = Double.parseDouble(width),
				h = Double.parseDouble(height);
		Phys2DWorld p2dw = (Phys2DWorld) w;
		p2dw.setWidth(wi);
		p2dw.setHeight(h);
	}
	
	@Override
	protected Phys2DWorld getDefaultWorld(String width, String height) {
		double w = Double.parseDouble(width),
				h = Double.parseDouble(height);
		Phys2DWorld world = new Phys2DGridWorld(2, 1f/60f, 8, 8, w/8, h/8);
		world.setWidth(w);
		world.setHeight(h);
		world.setGravity(0,0);
		createWalls(world);
		return world;
	}
	
	@Override
	protected Phys2DBody getDefaultBody(int type) {
		return new Phys2DBody( new StaticBox(25f, 25f), 0, true );
	}
	
	protected void createWalls(Phys2DWorld world) {
		float width = (float)world.getWidth(),
				height = (float)world.getHeight(),
				wallwidth = 10;
		
		Phys2DBody wall = new Phys2DBody("Wall1", new StaticBox(width, wallwidth), 0, true);
		wall.setPosition((float)0.5*width, (float)0.5*wallwidth);
		world.addBody(wall);
		
		wall = new Phys2DBody("Wall2", new StaticBox(width, wallwidth), 0, true);
		wall.setPosition((float)0.5*width, height - (float)0.5*wallwidth);
		world.addBody(wall);
		
		wall = new Phys2DBody("Wall3", new StaticBox(wallwidth, height), 0, true);
		wall.setPosition((float)0.5*wallwidth, (float)0.5*height);
		world.addBody(wall);
		
		wall = new Phys2DBody("Wall4", new StaticBox(wallwidth, height), 0, true);
		wall.setPosition(width - (float)0.5*wallwidth, (float)0.5*height);
		world.addBody(wall);
	}
}
